package com.lzh.chatnote.chat.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.lzh.chatnote.chat.dao.ContactDao;
import com.lzh.chatnote.chat.dao.GroupMemberDao;
import com.lzh.chatnote.chat.dao.MessageDao;
import com.lzh.chatnote.chat.dao.RoomFriendDao;
import com.lzh.chatnote.chat.domain.entity.*;
import com.lzh.chatnote.chat.domain.enums.RoomStatusEnum;
import com.lzh.chatnote.chat.domain.vo.request.message.MessagePageReq;
import com.lzh.chatnote.chat.domain.vo.request.message.MessageSendReq;
import com.lzh.chatnote.chat.domain.vo.response.message.MessageResp;
import com.lzh.chatnote.chat.service.MessageService;
import com.lzh.chatnote.chat.service.adapter.MessageAdapter;
import com.lzh.chatnote.chat.service.cache.RoomCache;
import com.lzh.chatnote.chat.service.cache.RoomGroupCache;
import com.lzh.chatnote.chat.service.event.MessageSendEvent;
import com.lzh.chatnote.chat.service.strategy.AbstractMsgHandler;
import com.lzh.chatnote.chat.service.strategy.MsgFactoryHandler;
import com.lzh.chatnote.common.domian.vo.response.CursorPageBaseResp;
import com.lzh.chatnote.common.utils.AssertUtil;
import com.lzh.chatnote.common.utils.UserUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class MessageServiceImpl implements MessageService {

    @Resource
    private ContactDao contactDao;
    @Resource
    private RoomCache roomCache;
    @Resource
    private MessageDao messageDao;
    @Resource
    private RoomFriendDao roomFriendDao;
    @Resource
    private RoomGroupCache roomGroupCache;
    @Resource
    private GroupMemberDao groupMemberDao;
    @Resource
    private ApplicationEventPublisher applicationEvent;


    @Override
    public CursorPageBaseResp<MessageResp> queryCursorPage(MessagePageReq messagePageReq) {
        //获取当前用户id
        Long currentUserId = UserUtils.getCurrentUserId();
        //获取用户被拉黑在当前会话最后一条消息id
        Long lastMsgId = getLastMessageId(currentUserId, messagePageReq.getRoomId());
        //查询拉黑用户id todo
        Long blackUserId = 0L;
        //查询消息信息列表
        CursorPageBaseResp<Message> messageResp =  messageDao.queryPageMessage(messagePageReq, lastMsgId,blackUserId);
        if(messageResp.isEmpty()){
            return CursorPageBaseResp.buildEmpty();
        }
        return CursorPageBaseResp.buildVO(messageResp, getMsgRespBatch(messageResp.getList(),currentUserId));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long sendMsg(MessageSendReq messageSendReq, Long uuid) {
        //校验前端传的参数是否正确
        checkSendMsgReqArgs(messageSendReq,uuid);
        //通过工厂获取消息处理类
        AbstractMsgHandler abstractMsgHandler = MsgFactoryHandler.getStrategyNoNull(messageSendReq.getMsgType());
        //数据库保存消息
        Long msgId = abstractMsgHandler.checkAndSaveMsg(messageSendReq, uuid);
        //发布发送消息事件
        applicationEvent.publishEvent(new MessageSendEvent(this, msgId));
        return msgId;
    }

    @Override
    public MessageResp getMsgResp(List<Message> messageList, Long uid) {
        return CollUtil.getFirst(getMsgRespBatch(messageList, uid));
    }

    public MessageResp buildSendMsgResp(Long msgId,Long sendUid) {
        Message message = messageDao.getById(msgId);
        return getMsgResp(Collections.singletonList( message), sendUid);
    }

    private void checkSendMsgReqArgs(MessageSendReq messageSendReq, Long uuid) {
        Long roomId = messageSendReq.getRoomId();
        Room room = roomCache.getOne(roomId);
        if(room.isHotRoom()){
            //热点群聊只有官方群聊，不需进行校验
            return;
        }

        if(room.isSingleRoom()){
            //单聊
           RoomFriend roomFriend = roomFriendDao.queryRoomFriendByRoomId(roomId);
           //判断当前用户是否是在单聊两个用户一个
            AssertUtil.isTrue(roomFriend.getUid1().equals(uuid) || roomFriend.getUid2().equals(uuid), "当前用户不在该单聊中");
            //判断是否被拉黑,或者删除
            AssertUtil.equal(RoomStatusEnum.NORMAL.getType(),roomFriend.getStatus() , "当前被该用户拉黑或删除");
        }

        if(room.isGroupRoom()){
            //查询群聊
            RoomGroup roomGroup = roomGroupCache.getOne(roomId);
            //查询群聊用户
            GroupMember groupMember = groupMemberDao.queryGroupMember(roomGroup.getId(), uuid);
            //判断当前用户是否是群聊中的用户
            AssertUtil.isNotEmpty(groupMember, "当前用户不在该群聊中");
        }

    }


    private Long getLastMessageId(Long currentUserId, Long roomId) {
        Room room = roomCache.getOne(roomId);
        AssertUtil.isNotEmpty(room, "房间信息不存在");
        if (room.isHotRoom()) {
            return null;
        }
        Contact contact = contactDao.queryUserLastMsgId(currentUserId, roomId);
        return Optional.ofNullable(contact)
                .map(Contact::getLastMsgId)
                .orElse(null);
    }

    private List<MessageResp> getMsgRespBatch(List<Message> messageList,Long uid){
        return MessageAdapter.buildMsgResp(messageList, uid);
    }



}
